﻿using hyjx.comm.Exceptions;
using S7.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;

namespace hyjx.comm
{
    /// <summary>
    /// 数据转换器
    /// </summary>
    public static class DataConvertor
    {
        /// <summary>
        /// 转换成整型
        /// </summary>
        /// <param name="obj">要转换的对象</param>
        /// <returns>整型数</returns>
        /// <exception cref="DataConvertorToShortException">S7 数据转换器转换整型异常</exception>
        internal static short ToShort(this object obj)
        {
            if (obj == null)
                throw new DataConvertorToShortException(nameof(ArgumentNullException));

            try
            {
                short value = ((ushort)obj).ConvertToShort();
                return value;
            }
            catch(ArgumentNullException ex)
            {
                throw new DataConvertorToShortException(nameof(ArgumentNullException),ex);
            }
            catch (ArgumentException ex)
            {
                throw new DataConvertorToShortException(nameof(ArgumentException),ex);
            }
            catch(FormatException ex)
            {
                throw new DataConvertorToShortException(nameof(FormatException),ex);
            }
            catch(OverflowException ex)
            {
                throw new DataConvertorToShortException(nameof(OverflowException),ex);
            }
        }
        /// <summary>
        /// 转换成浮点型
        /// </summary>
        /// <param name="obj">要转换的对象</param>
        /// <returns>浮点型数</returns>
        /// <exception cref="DataConvertorToFloatException"> S7 数据转换器转换浮点型异常</exception>
        internal static float ToFloat(this object obj)
        {
            if (obj == null)
                throw new DataConvertorToFloatException(nameof(ArgumentNullException));

            try
            {
                float value = ((uint)obj).ConvertToFloat();
                return value;
            }
            catch (ArgumentNullException ex)
            {
                throw new DataConvertorToFloatException(nameof(ArgumentNullException), ex);
            }
            catch (ArgumentOutOfRangeException ex)
            {
                throw new DataConvertorToFloatException(nameof(ArgumentOutOfRangeException), ex);
            }
            catch (ArgumentException ex)
            {
                throw new DataConvertorToFloatException(nameof(ArgumentException), ex);
            }
        }

        /// <summary>
        /// 转换成布尔值
        /// </summary>
        /// <param name="obj">要转换的对象</param>
        /// <returns>布尔值</returns>
        /// <exception cref="DataConvertorToBoolException">S7 数据转换器转换布尔值异常</exception>
        internal static bool ToBool(this object obj)
        {
            if (obj == null)
                throw new DataConvertorToBoolException(nameof(ArgumentNullException));

            try
            {
                bool value = (bool)obj;
                return value;
            }
            catch(Exception ex)
            {
                throw new DataConvertorToBoolException(nameof(Exception), ex);
            }
        }

        /// <summary>
        /// 转换成字符串
        /// </summary>
        /// <param name="bytes">要转换的字节数组</param>
        /// <param name="encoding">字符编码</param>
        /// <returns>字符串</returns>
        /// <exception cref="DataConvertorToStringException">S7 数据转换器转换字符串异常</exception>
        public static string FromBytesToString(this byte[] bytes, Encoding encoding)
        {
            if (bytes == null || bytes.Length == 0)
                throw new DataConvertorToStringException(nameof(ArgumentNullException));

            try
            {
                string str = encoding.GetString(bytes);
                str = str.Replace("\f", string.Empty);
                str = str.Replace("\n", string.Empty);
                str = str.Replace("\0", string.Empty);
                return str;
            }
            catch (ArgumentNullException ex)
            {
                throw new DataConvertorToStringException(nameof(ArgumentNullException), ex);
            }
            catch (DecoderFallbackException ex)
            {
                throw new DataConvertorToStringException(nameof(DecoderFallbackException), ex);
            }
            catch (ArgumentException ex)
            {
                throw new DataConvertorToStringException(nameof(ArgumentException), ex);
            }
        }
        /// <summary>
        /// 字节转换为八个布尔值
        /// </summary>
        /// <param name="data">字节数据</param>
        /// <returns>布尔集合</returns>
        public static List<bool> FromByteTo8Bool(this byte data)
        {
            List<bool> result = new List<bool>()
            {
                (byte)(data & 0x01) == 0x01,
                (byte)(data & 0x02) == 0x02,
                (byte)(data & 0x04) == 0x04,
                (byte)(data & 0x08) == 0x08,
                (byte)(data & 0x10) == 0x10,
                (byte)(data & 0x20) == 0x20,
                (byte)(data & 0x40) == 0x40,
                (byte)(data & 0x80) == 0x80
            };
            return result;
        }
        /// <summary>
        /// 自己数组转为布尔集合
        /// </summary>
        /// <param name="datas">字节数组</param>
        /// <returns></returns>
        public static List<bool> FromBytesToBools(this byte[] datas)
        {
            List<bool> result = new List<bool>();
            foreach (var item in datas)
            {
                result.AddRange(FromByteTo8Bool(item));
            }
            return result;
        }
        /// <summary>
        /// 字节数组转换为整型
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>整型</returns>
        /// <exception cref="DataConvertorToShortException">转换整型失败</exception>
        public static short FromBytesToShort(this byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
                throw new DataConvertorToShortException(nameof(ArgumentNullException));

            try
            {
                return BitConverter.ToInt16(bytes.Reverse().ToArray(), 0);
            }
            catch (ArgumentNullException ex)
            {
                throw new DataConvertorToShortException(nameof(ArgumentNullException), ex);
            }
            catch (ArgumentOutOfRangeException ex)
            {
                throw new DataConvertorToShortException(nameof(ArgumentOutOfRangeException), ex);
            }
            catch (ArgumentException ex)
            {
                throw new DataConvertorToShortException(nameof(ArgumentException), ex);
            }
        }
        /// <summary>
        /// 字节数组转换为浮点数
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>浮点数</returns>
        /// <exception cref="DataConvertorToFloatException">转换浮点数失败</exception>
        public static float FromBytesToFloat(this byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
                throw new DataConvertorToFloatException(nameof(ArgumentNullException));

            try
            {
                return BitConverter.ToSingle(bytes.Reverse().ToArray(), 0);
            }
            catch (ArgumentNullException ex)
            {
                throw new DataConvertorToFloatException(nameof(ArgumentNullException), ex);
            }
            catch (ArgumentOutOfRangeException ex)
            {
                throw new DataConvertorToFloatException(nameof(ArgumentOutOfRangeException), ex);
            }
            catch (ArgumentException ex)
            {
                throw new DataConvertorToFloatException(nameof(ArgumentException), ex);
            }
        }
    }
}